#include "stdafx.h"
#include "XRequest.h"
#include "XModem.h"
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include "VanException.h"
#include "Utils.h"

XRequest::XRequest()
{
	m_bInReq = false;
	m_RespResult = 0;
	m_Uart.SetOnRecv(this);

	sem_init(&m_hSem, 0, 0);
}

XRequest::~XRequest()
{
	Close();
	Notify();

	sem_destroy(&m_hSem);
}

bool XRequest::Open()
{
	Close();

	return m_Uart.Open("/dev/ttyHSL1", B115200);
}

bool XRequest::IsOpen()
{
	return m_Uart.IsOpen();
}

void XRequest::Close()
{
	m_Uart.Close();
}

int XRequest::Wait(int timeout)
{
	struct timespec ts;

    if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
		return -1;
	}

    ts.tv_sec  += timeout/1000;
    ts.tv_nsec += timeout%1000*1000000;

    return sem_timedwait(&m_hSem, &ts);
}

void XRequest::Notify()
{
	sem_post(&m_hSem);
}

bool XRequest::Request(const byte* pBuf, int length, bool waitResp)
{
	if (!IsOpen()) {
		throw new VanException(EC_NOT_CONNECTED);
	}

	m_Lock.Lock();
	VanException* pException = NULL;

	try {
		RequestInner(pBuf, length, waitResp);
	} catch (VanException* e) {
		pException = e;
	}

	m_bInReq = false;
	m_Lock.Unlock();

	if (NULL != pException) {
		throw pException;
	}

	if (!waitResp) {
		return true;
	}

	bool bRet = false;
	if (6 == m_RespResult) {
		bRet = true;
	} else if (21 == m_RespResult) {
		bRet = false;
	} else {

	}

	return bRet;
}

void XRequest::RequestInner(const byte* pBuf, int length, bool waitResp)
{
	m_bInReq = true;
	m_RespResult = 0;

	int size = m_Uart.Write(pBuf, length);

	if (size < length) {
		throw new VanException(EC_SEND_FAILED);
	}

	if (!waitResp) {
		return;
	}

	int result = Wait(5000);
	if (0 != result) {
		if (ETIMEDOUT == errno) {
			throw new VanException(EC_RESP_TIMEOUT);
		} else {
			throw new VanException(EC_UNKNOWN);
		}
	}
}

void XRequest::OnRecv(const byte* pBuf, int length)
{
	for (int i = 0; i < length; ++i)
	{
		if (67 == pBuf[i])
		{
			XModem::Instance()->OnChar();
		}
		else
		{
			if (m_bInReq) {
				m_RespResult = pBuf[i];
				Notify();
				usleep(5000);
			} else {
				printf("XModem Recv Error Char: %c\n", pBuf[i]);
			}
		}
	}
}
